package com.zkyc.framework.website.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zkyc.framework.common.constant.NumberConstant;
import com.zkyc.framework.common.exception.ResultCode;
import com.zkyc.framework.common.mapper.ColumnDataClickRateMapper;
import com.zkyc.framework.common.mapper.FileMapper;
import com.zkyc.framework.common.pojo.*;
import com.zkyc.framework.common.pool.GlobalThreadPoolExecutor;
import com.zkyc.framework.common.utils.PageUtil;
import com.zkyc.framework.common.utils.WebsiteUtil;
import com.zkyc.framework.common.vo.ResultVO;
import com.zkyc.framework.common.vo.website.*;
import com.zkyc.framework.website.client.AlgorithmClient;
import com.zkyc.framework.website.client.UserClient;
import com.zkyc.framework.website.config.JedisPoolFactory;
import com.zkyc.framework.website.constant.WebsiteConstant;
import com.zkyc.framework.website.mapper.*;
import com.zkyc.framework.website.service.ColumnService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.CollectionUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.zkyc.framework.common.constant.Constant.*;

/**
 * (Column)表服务实现类
 *
 * @author libingchuan
 * @since 2022-05-25 15:04:33
 */
@Slf4j
@Service("columnService")
public class ColumnServiceImpl implements ColumnService {
    @Autowired
    private ColumnMapper columnMapper;
    @Autowired
    private TagMapper tagMapper;
    @Autowired
    private MoudleMapper moudleMapper;
    @Autowired
    private ColumnComponentMapper columnComponentMapper;
    @Autowired
    private ColumnDataMapper columnDataMapper;
    @Autowired
    private ColumnRefComponentMapper refComponentMapper;
    @Autowired
    private FileRefColumnDataMapper fileRefColumnDataMapper;
    @Autowired
    private FileMapper fileMapper;
    @Autowired
    private ColumnDataRefMediaTagMapper refMediaTagMapper;
    @Autowired
    private ColumnRefColumnDataMapper refColumnDataMapper;
    @Autowired
    private ColumnDataClickRateMapper dataClickRateMapper;
    @Autowired
    private ModuleTemplateMapper moduleTemplateMapper;
    @Autowired
    private ColumnTemplateMapper columnTemplateMapper;
    @Autowired
    private ColRefComPlateMapper comPlateMapper;

    @Autowired
    private UserClient userClient;
    @Autowired
    private AlgorithmClient algorithmClient;
    @Autowired
    private PlatformTransactionManager transactionManager;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public Column queryById(Integer id) {
        Column column = columnMapper.selectById(id);
        setTagList(column);
        return column;
    }

    /**
     * 通过ID查询单条数据
     *
     * @param moudleId 主键
     * @return 实例对象
     */
    @Override
    public List<Column> queryByMoudleId(Integer moudleId) {
        QueryWrapper<Column> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("moudle_id", moudleId);
        List<Column> columns = columnMapper.selectList(queryWrapper);
        for (Column column : columns) {
            setTagList(column);
        }
        return columns;
    }

    /**
     * 查询
     *
     * @return 查询结果
     */
    @Override
    public ResultVO queryList(Integer columnType) {
        QueryWrapper<Column> queryWrapper = getColumnQueryWrapper();
        if (columnType != null) {
            queryWrapper.eq("column_type", columnType);
        }
        String websiteId = WebsiteUtil.getWebsiteId();
        if (StringUtils.isNotBlank(websiteId)) {
            List<Integer> ids = moudleMapper.queryMoudleByWebsiteId(websiteId);
            queryWrapper.in("moudle_id", ids);
        }
        List<Column> columns = columnMapper.selectList(queryWrapper);
        for (Column column : columns) {
            setTagList(column);
        }
        return ResultVO.data(columns);

    }


    /**
     * 新增数据
     *
     * @param column 实例对象
     * @return 实例对象
     */
    @Override
    public ResultVO insert(Column column) {
        if (column == null) {
            return ResultVO.fail(ResultCode.PARAM_INVALID);
        }
        columnMapper.insert(column);
        insertTag(column);
        return ResultVO.success(ResultCode.SUCCESS);
    }

    private void insertTag(Column column) {
        if (column.getTagList() != null) {
            List<Tag> tagList = column.getTagList();
            Integer columnId = column.getId();
            tagList.forEach(tag -> {
                tag.setColumnId(columnId);
                if (tag.getTagValueJson() != null) {
                    tag.setTagValue(tag.getTagValueJson().toJSONString());
                }
                tagMapper.insert(tag);
            });
        }
    }

    /**
     * 修改数据
     *
     * @param column 实例对象
     * @return 实例对象
     */
    @Override
    public ResultVO update(Column column) {
        if (column == null) {
            return ResultVO.fail(ResultCode.PARAM_INVALID);
        }
        if (queryById(column.getId()) == null) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        columnMapper.updateById(column);
        deleteTag(column);
        insertTag(column);
        return ResultVO.success(ResultCode.SUCCESS);
    }

    /**
     * 修改数据
     *
     * @param column 实例对象
     * @return 实例对象
     */
    @Override
    public ResultVO updateName(Column column) {
        if (column == null) {
            return ResultVO.fail(ResultCode.PARAM_INVALID);
        }
        Column column1 = columnMapper.selectById(column.getId());
        if (column1 == null) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        if (column.getColumnName() != null) {
            column1.setColumnName(column.getColumnName());
        }
        columnMapper.updateById(column);
        return ResultVO.success(ResultCode.SUCCESS);
    }

    private void deleteTag(Column column) {
        if (column.getTagList() != null) {
            QueryWrapper<Tag> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("column_id", column.getId());
            List<Tag> tagList = tagMapper.selectList(queryWrapper);
            tagList.forEach(tag -> tagMapper.deleteById(tag));
        }
    }

    /**
     * 通过主键隐藏数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public ResultVO hideById(Integer id) {
        if (id == null) {
            return ResultVO.fail(ResultCode.PARAM_INVALID);
        }
        Column column = queryById(id);
        if (column == null) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        columnMapper.updateById(column);
        return ResultVO.success(ResultCode.SUCCESS);
    }

    /**
     * 查询is_show字段
     *
     * @return 查询结果
     */
    private QueryWrapper<Column> getColumnQueryWrapper() {
        return new QueryWrapper<>();
    }

    public void setTagList(Column column) {
        if (column.getColumnType() != null) {
            QueryWrapper<Tag> tagQueryWrapper = new QueryWrapper<>();
            tagQueryWrapper.eq("column_id", column.getId());
            tagQueryWrapper.orderByAsc("tag_order");
            List<Tag> tags = tagMapper.selectList(tagQueryWrapper);
            for (Tag tag : tags) {
                if (tag.getTagKey().equals("profile") || tag.getTagKey().equals("peopleIntroduce") || tag.getTagKey().equals("imgIntroduce")
                        || tag.getTagKey().equals("imgUrl")) {
                    if (StringUtils.isNotBlank(tag.getTagValue())) {
                        JSONArray jsonArray = JSONArray.parseArray(tag.getTagValue());
                        tag.setTagValueJson(jsonArray);
                    }
                }
            }
            column.setTagList(tags);
        }
    }

    @Override
    public ResultVO<?> getComponents() {
        LambdaQueryWrapper<ColumnComponent> componentLqw = new LambdaQueryWrapper<>();
        componentLqw.eq(ColumnComponent::getColumnId, -1);
        List<ColumnComponent> columnComponentList = columnComponentMapper.selectList(componentLqw);
        return ResultVO.data(columnComponentList);
    }

    @Override
    @Transactional
    public ResultVO<?> add(ColumnSaveVo columnSaveVo) {
        if (columnSaveVo == null) {
            return ResultVO.fail(ResultCode.PARAM_INVALID);
        }
        Column column = new Column();
        BeanUtils.copyProperties(columnSaveVo, column);
        column.setColumnCount(NumberConstant.NUMBER_5);

        columnMapper.insert(column);
        List<Integer> componentIdList = columnSaveVo.getComponentIdList();
        if (!CollectionUtils.isEmpty(componentIdList)) {
            // 不为空才需要这一步
            List<ColumnRefComponent> columnRefComponentList = getColumnRefComponentList(componentIdList, column.getId());
            refComponentMapper.insertBatch(columnRefComponentList);
        }
        return ResultVO.success(ResultCode.SUCCESS);
    }

    private static List<ColumnRefComponent> getColumnRefComponentList(List<Integer> componentIdList, Integer columnId) {
        List<ColumnRefComponent> columnRefComponentList = new ArrayList<>(componentIdList.size());
        componentIdList.forEach(componentId -> {
            ColumnRefComponent columnRefComponent = new ColumnRefComponent();
            columnRefComponent.setColumnId(columnId);
            columnRefComponent.setComponentId(componentId);
            columnRefComponentList.add(columnRefComponent);
        });
        return columnRefComponentList;
    }

    @Override
    public ResultVO<?> queryDataByMoudleId(Integer moudleId) {
        // 获取栏目数据
        List<Column> columnList = getColumnList(moudleId);
        List<ColumnType2> columnType2List = new ArrayList<>(columnList.size());
        columnList.forEach(column -> {
            ColumnType2 columnType2 = getColumnType2Data(column);
            columnType2List.add(columnType2);
        });
        return ResultVO.data(columnType2List);
    }

    private ColumnType2 getColumnType2Data(Column column) {
        ColumnType2 columnType2 = new ColumnType2();
        BeanUtils.copyProperties(column, columnType2);
        // 查询该栏目下的数据
        LambdaQueryWrapper<ColumnData> dataLqw = new LambdaQueryWrapper<>();
        // 只要已发布的
        dataLqw.eq(ColumnData::getColumnId, column.getId()).orderByDesc(ColumnData::getOrderNum).eq(ColumnData::getStatus, NumberConstant.NUMBER_1);
        List<ColumnData> columnDataList = columnDataMapper.selectList(dataLqw);

        handleColumnDataFilePlus(columnDataList, columnDataList.stream().map(ColumnData::getId).collect(Collectors.toList()));
        columnType2.setData(columnDataList);
        return columnType2;
    }

    @Override
    public ResultVO<?> queryDataByColumnId(Integer columnId) {
        Column column = columnMapper.selectById(columnId);
        ColumnDataPageVo columnDataPageVo = new ColumnDataPageVo();

        columnDataPageVo.setColumnType(column.getColumnType());
        columnDataPageVo.setColumnId(columnId);
        columnDataPageVo.setStatus(NumberConstant.NUMBER_1);

        ColumnType2 columnType2 = new ColumnType2();
        BeanUtils.copyProperties(column, columnType2);
        columnType2.setData(getColumnData(columnDataPageVo));
        return ResultVO.data(columnType2);
    }

    private List<ColumnData> getColumnData(ColumnDataPageVo columnDataPageVo) {

        List<ColumnData> columnDataList;

        LambdaQueryWrapper<ColumnData> columnDataLqw = new LambdaQueryWrapper<>();
        Integer columnType = columnDataPageVo.getColumnType();
        if (Objects.equals(columnType, 3) || Objects.equals(columnType, 5)) {
            // 需要先查中间表
            List<ColumnRefColumnData> columnRefColumnDataList = getColumnRefColumnDataList(columnDataPageVo);
            List<Integer> columnDataIdList = columnRefColumnDataList.stream().map(ColumnRefColumnData::getColumnDataId).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(columnDataIdList)) {
                return Collections.emptyList();
            }
            columnDataLqw.in(ColumnData::getId, columnDataIdList);

            preQueryColumnData(columnDataLqw, columnDataPageVo);
            // 需要更改顺序
            List<ColumnData> records = columnDataMapper.selectList(columnDataLqw);
            columnDataList = new ArrayList<>(records.size());
            columnRefColumnDataList.forEach(refColumnData -> records.forEach(record -> {
                if (Objects.equals(record.getId(), refColumnData.getColumnDataId())) {
                    record.setRefColumnDataId(refColumnData.getId());
                    columnDataList.add(record);
                }
            }));
        } else {
            columnDataLqw.eq(Objects.nonNull(columnDataPageVo.getColumnId()), ColumnData::getColumnId, columnDataPageVo.getColumnId());

            preQueryColumnData(columnDataLqw, columnDataPageVo);

            // 根据排序数来排序
            columnDataLqw.orderByDesc(ColumnData::getOrderNum);
            columnDataList = columnDataMapper.selectList(columnDataLqw);
        }

        handleColumnDataFilePlus(columnDataList, columnDataList.stream().map(ColumnData::getId).collect(Collectors.toList()));
        return columnDataList;
    }

    private List<ColumnRefColumnData> getColumnRefColumnDataList(ColumnDataPageVo columnDataPageVo) {
        LambdaQueryWrapper<ColumnRefColumnData> refColumnDataLqw = new LambdaQueryWrapper<>();
        refColumnDataLqw.eq(ColumnRefColumnData::getColumnId, columnDataPageVo.getColumnId()).orderByDesc(ColumnRefColumnData::getOrderNum);
        return refColumnDataMapper.selectList(refColumnDataLqw);
    }

    @Override
    public ResultVO<?> queryBannerByMoudleId(Integer moudleId) {
        // 这个缓存可以不清
        String resultStr = JedisPoolFactory.select(REDIS_PREFIX + COLUMN_LIST + moudleId);
        if (resultStr != null) {
            return ResultVO.data(JSONArray.parseArray(resultStr));
        }
        List<Column> columnList = getColumnList(moudleId);
        JedisPoolFactory.setex(REDIS_PREFIX + COLUMN_LIST + moudleId, 30, JSONArray.toJSONString(columnList, SerializerFeature.WriteDateUseDateFormat));
        return ResultVO.data(columnList);
    }

    @Override
    // @Transactional
    public ResultVO refData(ColumnDataRefVo columnDataRefVo) {
        Integer columnDataId = columnDataRefVo.getId();
        if (columnDataId == null) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        List<Integer> columnIdList = columnDataRefVo.getColumnId();
        List<ColumnRefColumnData> columnRefColumnDataList = new ArrayList<>(columnIdList.size());
        for (Integer columnId : columnIdList) {
            if (columnId == null) {
                return ResultVO.fail(ResultCode.SERVE_ERROR);
            }
            ColumnRefColumnData columnRefColumnData = new ColumnRefColumnData();
            columnRefColumnData.setColumnDataId(columnDataId);
            columnRefColumnData.setColumnId(columnId);
            columnRefColumnData.setOrderNum(System.currentTimeMillis());
            columnRefColumnDataList.add(columnRefColumnData);
            // 清除缓存
            JedisPoolFactory.scanAndDel(REDIS_PREFIX + COLUMN_DATA_LIST + columnId);
        }

        // 同一稿件，先删后增
        LambdaQueryWrapper<ColumnRefColumnData> refColumnDataLqw = getColumnRefColumnDataLqw(columnDataId);
        refColumnDataMapper.delete(refColumnDataLqw);
        if (!CollectionUtils.isEmpty(columnRefColumnDataList)) {
            refColumnDataMapper.insertBatch(columnRefColumnDataList);
        }
        return ResultVO.success(ResultCode.SUCCESS);
    }

    @Override
    public ResultVO removeRef(ColumnData columnData) {
        ColumnRefColumnData columnRefColumnData = refColumnDataMapper.selectById(columnData.getRefColumnDataId());
        if (columnRefColumnData == null) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        columnData.setId(columnRefColumnData.getColumnDataId());
        refColumnDataMapper.deleteById(columnData.getRefColumnDataId());
        // 清除缓存
        JedisPoolFactory.scanAndDel(REDIS_PREFIX + COLUMN_DATA_LIST + columnRefColumnData.getColumnId());
        return ResultVO.success(ResultCode.SUCCESS);
    }

    @Override
    public ResultVO top(ColumnDataPageVo columnDataPageVo) {
        Integer columnType = columnDataPageVo.getColumnType();
        if (Objects.equals(columnType, 3) || Objects.equals(columnType, 5)) {
            LambdaUpdateWrapper<ColumnRefColumnData> refColumnDataLuw = new LambdaUpdateWrapper<>();
            refColumnDataLuw.eq(ColumnRefColumnData::getId, columnDataPageVo.getRefColumnDataId()).set(ColumnRefColumnData::getOrderNum, System.currentTimeMillis());
            refColumnDataMapper.update(null, refColumnDataLuw);
        } else {
            LambdaUpdateWrapper<ColumnData> columnDataLuw = new LambdaUpdateWrapper<>();
            columnDataLuw.eq(ColumnData::getId, columnDataPageVo.getId()).set(ColumnData::getOrderNum, System.currentTimeMillis());
            columnDataMapper.update(null, columnDataLuw);
        }
        return ResultVO.success(ResultCode.SUCCESS);
    }

    private List<Column> getColumnList(Integer moudleId) {
        LambdaQueryWrapper<Column> columnLqw = new LambdaQueryWrapper<>();
        columnLqw.eq(Column::getMoudleId, moudleId);
        return columnMapper.selectList(columnLqw);
    }

    @Override
    public ResultVO<?> queryColumnByMoudleId(Integer moudleId) {
        List<Column> columnList = getColumnList(moudleId);
        List<Integer> columnIdList = columnList.stream().map(Column::getId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(columnIdList)) {
            return getListResultVO(columnList);
        }
        // 首先查中间表
        LambdaQueryWrapper<ColumnRefComponent> columnRefComponentLqw = new LambdaQueryWrapper<>();
        columnRefComponentLqw.in(ColumnRefComponent::getColumnId, columnIdList);
        List<ColumnRefComponent> columnRefComponentList = refComponentMapper.selectList(columnRefComponentLqw);
        // 再查组件表,根据圆柱id进行分组,转为Map，还要把圆柱id为0的取出
        List<Integer> componentIds = columnRefComponentList.stream().map(ColumnRefComponent::getComponentId).distinct().collect(Collectors.toList());
        LambdaQueryWrapper<ColumnComponent> columnComponentLqw = new LambdaQueryWrapper<>();
        // 会不会报错
        if (CollectionUtils.isEmpty(componentIds)) {
            return getListResultVO(columnList);
        }
        columnComponentLqw.in(ColumnComponent::getId, componentIds);
        columnComponentLqw.or().eq(ColumnComponent::getColumnId, NumberConstant.NUMBER_0);
        // 根据圆柱id升序排序
        columnComponentLqw.orderByAsc(ColumnComponent::getColumnId);
        List<ColumnComponent> columnComponentList = columnComponentMapper.selectList(columnComponentLqw);
        List<ColumnComponent> commonComponents = columnComponentList.stream()
                .filter(columnComponent -> Objects.equals(columnComponent.getColumnId(), NumberConstant.NUMBER_0)).collect(Collectors.toList());
        // 取出发布时间组件对象
        Map<Integer, ColumnComponent> idComponentMap = columnComponentList.stream().collect(Collectors.toMap(ColumnComponent::getId, columnComponent -> columnComponent));
        // 中间表根据栏目id进行分组，要注意排序
        Map<Integer, List<ColumnRefComponent>> columnIdComponentsMap = columnRefComponentList
                .stream().collect(Collectors.groupingBy(ColumnRefComponent::getColumnId, LinkedHashMap::new, Collectors.toList()));
        List<ColumnType2> columnType2List = columnList.stream().map(column -> {
            ColumnType2 columnType2 = new ColumnType2();
            BeanUtils.copyProperties(column, columnType2);
            List<ColumnRefComponent> columnRefComponentListForColumn = columnIdComponentsMap.get(column.getId());
            if (CollectionUtils.isEmpty(columnRefComponentListForColumn)) {
                return columnType2;
            }
            // 正常情况肯定能取到值
            List<ColumnComponent> componentListTemp = columnRefComponentListForColumn.stream()
                    .map(columnRefComponent -> idComponentMap.get(columnRefComponent.getComponentId())).collect(Collectors.toList());

            componentListTemp.addAll(commonComponents);
            columnType2.setData(componentListTemp);
            return columnType2;
        }).collect(Collectors.toList());
        return ResultVO.data(columnType2List);
    }

    private ResultVO<List<ColumnType2>> getListResultVO(List<Column> columnList) {
        List<ColumnType2> columnType2List = columnList.stream().map(column -> {
            ColumnType2 columnType2 = new ColumnType2();
            BeanUtils.copyProperties(column, columnType2);
            return columnType2;
        }).collect(Collectors.toList());
        return ResultVO.data(columnType2List);
    }

    @Override
    @Transactional
    public ResultVO addData(ColumnData columnData) {
        String title = columnData.getTitle();
        Integer columnId = columnData.getColumnId();
        if (StringUtils.isNotBlank(title) && columnId != null) {
            // 标题不为空时要判断同栏目下是否已经存在
            List<ColumnData> columnDataList = getColumnDataList(title, columnId);
            if (columnDataList.size() > 0) {
                return ResultVO.fail("该标题已经存在");
            }
        }

        handleColumnDataForSave(columnData);

        columnDataMapper.insert(columnData);

        List<FileRefColumnData> fileRefColumnDataList;
        try {
            fileRefColumnDataList = getFileRefColumnDataPlus(columnData);
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.error("保存栏目数据发生异常：" + e);
            return ResultVO.fail(e.getMessage());
        }
        if (!CollectionUtils.isEmpty(fileRefColumnDataList)) {
            fileRefColumnDataMapper.insertBatch(fileRefColumnDataList);
        }

        List<List<Integer>> tagId = columnData.getTagId();
        if (!CollectionUtils.isEmpty(tagId)) {
            // tagId不为空才需要以下操作
            List<ColumnDataRefMediaTag> columnDataRefMediaTagList;
            try {
                columnDataRefMediaTagList = getColumnDataRefMediaTagList(columnData.getId(), tagId);
            } catch (Exception e) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                log.error("保存栏目数据发生异常：" + e.getMessage());
                return ResultVO.fail(ResultCode.SERVE_ERROR);
            }
            refMediaTagMapper.insertBatch(columnDataRefMediaTagList);
        }

        // 自动推荐
        Integer refColumnId = WebsiteConstant.REF_MAP.get(columnId);
        if (refColumnId != null) {
            List<Integer> refColumnIdList = new ArrayList<>(NumberConstant.NUMBER_1);
            refColumnIdList.add(refColumnId);
            // 推荐到对应的栏目
            ColumnDataRefVo columnDataRefVo = new ColumnDataRefVo();
            columnDataRefVo.setId(columnData.getId());
            columnDataRefVo.setColumnId(refColumnIdList);
            this.refData(columnDataRefVo);
        }
        return ResultVO.data(ResultCode.SUCCESS);
    }

    private List<ColumnData> getColumnDataList(String title, Integer columnId) {
        LambdaQueryWrapper<ColumnData> columnDataLqw = new LambdaQueryWrapper<>();
        columnDataLqw.select(ColumnData::getId);
        columnDataLqw.eq(ColumnData::getColumnId, columnId).eq(ColumnData::getTitle, title);
        return columnDataMapper.selectList(columnDataLqw);
    }

    private void handleColumnDataForSave(ColumnData columnData) {
        // 初始状态未发布,并设置排序数
        columnData.setStatus(NumberConstant.NUMBER_0);
        columnData.setOrderNum(System.currentTimeMillis());
        // 添加网站id和原始内容
        if (columnData.getIntroduce() != null) {
            columnData.setOriginalContent(Jsoup.clean(columnData.getIntroduce(), Whitelist.none()));
        }
        // 将用户id转为用户名
        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(userClient.getUserById(columnData.getCreatedBy())));
        String username = JSONObject.parseObject(jsonObject.getString("data"), new TypeReference<User>() {
        }).getUsername();
        columnData.setCreatedBy(username);
        // path
        LambdaQueryWrapper<Column> columnLqw = new LambdaQueryWrapper<>();
        columnLqw.select(Column::getMoudleId, Column::getColumnName).eq(Column::getId, columnData.getColumnId());
        Column column = columnMapper.selectOne(columnLqw);
        LambdaQueryWrapper<Moudle> moudleLqw = new LambdaQueryWrapper<>();
        moudleLqw.select(Moudle::getMoudleName).eq(Moudle::getId, column.getMoudleId());
        Moudle moudle = moudleMapper.selectOne(moudleLqw);
        columnData.setPath(moudle.getMoudleName() + "/" + column.getColumnName());
    }

    // 待优化
    private List<FileRefColumnData> getFileRefColumnDataPlus(ColumnData columnData) {
        Integer columnDataId = columnData.getId();
        List<FileRefColumnData> fileRefColumnDataList = new ArrayList<>();
        List<File>[] fileListArray = new List[4];
        fileListArray[NumberConstant.NUMBER_0] = columnData.getUploadImg();
        fileListArray[NumberConstant.NUMBER_1] = columnData.getUploadVideo();
        fileListArray[NumberConstant.NUMBER_2] = columnData.getAttachment();
        fileListArray[NumberConstant.NUMBER_3] = columnData.getFile();
        for (int i = 0; i < fileListArray.length; i++) {
            if (!CollectionUtils.isEmpty(fileListArray[i])) {
                insertFileRefDataList(columnDataId, fileRefColumnDataList, fileListArray[i], i);
            }
        }
        return fileRefColumnDataList;
    }

    private void insertFileRefDataList(Integer columnDataId, List<FileRefColumnData> fileRefColumnDataList, List<File> fileList, Integer fileType) {
        fileList.forEach(file -> {
            if (file == null || file.getId() == null) {
                throw new RuntimeException("上传文件过程出现异常");
            }
            FileRefColumnData fileRefColumnData = new FileRefColumnData();
            fileRefColumnData.setColumnDataId(columnDataId);
            fileRefColumnData.setFileId(file.getId());
            fileRefColumnData.setFileType(fileType);
            fileRefColumnDataList.add(fileRefColumnData);
        });
    }

    private List<ColumnDataRefMediaTag> getColumnDataRefMediaTagList(Integer columnDataId, List<List<Integer>> tagId) {
        List<ColumnDataRefMediaTag> columnDataRefMediaTagList = new ArrayList<>(tagId.size());
        tagId.forEach(tagArray -> {
            ColumnDataRefMediaTag columnDataRefMediaTag = new ColumnDataRefMediaTag();
            columnDataRefMediaTag.setColumnDataId(columnDataId);
            Integer tag0 = tagArray.get(NumberConstant.NUMBER_0);
            Integer tag1 = tagArray.get(NumberConstant.NUMBER_1);
            if (tag1 == null || tag0 == null) {
                throw new RuntimeException("标签组异常");
            }
            columnDataRefMediaTag.setMediaTagGroupId(tag0);
            columnDataRefMediaTag.setMediaTagId(tag1);
            columnDataRefMediaTagList.add(columnDataRefMediaTag);
        });
        return columnDataRefMediaTagList;
    }

    @Override
    public ResultVO neoQuery(ColumnDataPageVo columnDataPageVo) {
        columnDataPageVo.check();
        Integer columnType = columnDataPageVo.getColumnType();
        IPage<ColumnData> columnDataIPage = getColumnDataIPage(columnDataPageVo, new LambdaQueryWrapper<>(), NumberConstant.NUMBER_0);
        List<ColumnData> columnDataList = columnDataIPage.getRecords();
        List<Integer> columnDataIdList = columnDataList.stream().map(ColumnData::getId).collect(Collectors.toList());
        // 1.处理文件
        handleColumnDataFilePlus(columnDataList, columnDataIdList);
        // 2.只有2需要处理标签
        if (Objects.equals(columnType, NumberConstant.NUMBER_2)) {
            handleColumnDataTagIdPlus(columnDataList, columnDataIdList);
        }
        // 3.只要不是1都需要处理点击量
        if (!Objects.equals(columnType, NumberConstant.NUMBER_1)) {
            handleColumnDataClickPlus(columnDataList, columnDataIdList);
        }
        // 4.只有2，4可以被推荐，需要获取已被推荐的栏目id
        if (Objects.equals(columnType, NumberConstant.NUMBER_2) || Objects.equals(columnType, NumberConstant.NUMBER_4)) {
            handleColumnDataRefColumnIdsPlus(columnDataList, columnDataIdList);
        }
        return ResultVO.data(columnDataIPage);
    }

    private void handleColumnDataRefColumnIdsPlus(List<ColumnData> columnDataList, List<Integer> columnDataIdList) {
        if (CollectionUtils.isEmpty(columnDataIdList)) {
            return;
        }
        LambdaQueryWrapper<ColumnRefColumnData> columnRefColumnDataLqw = new LambdaQueryWrapper<>();
        columnRefColumnDataLqw.in(ColumnRefColumnData::getColumnDataId, columnDataIdList);
        List<ColumnRefColumnData> columnRefColumnDataList = refColumnDataMapper.selectList(columnRefColumnDataLqw);
        if (CollectionUtils.isEmpty(columnRefColumnDataList)) {
            // 为空则不需要继续
            return;
        }
        // 根据dataId进行分组,不需要顺序
        Map<Integer, List<ColumnRefColumnData>> dataIdColumnIdsMap = columnRefColumnDataList.stream().collect(Collectors.groupingBy(ColumnRefColumnData::getColumnDataId));
        columnDataList.forEach(data -> {
            List<ColumnRefColumnData> columnRefColumnDataListForData = dataIdColumnIdsMap.get(data.getId());
            if (CollectionUtils.isEmpty(columnRefColumnDataListForData)) {
                return;
            }
            data.setRefColumnIdList(columnRefColumnDataListForData.stream().map(ColumnRefColumnData::getColumnId).collect(Collectors.toList()));
        });
    }

    private void handleColumnDataClickPlus(List<ColumnData> columnDataList, List<Integer> columnDataIdList) {
        if (CollectionUtils.isEmpty(columnDataIdList)) {
            return;
        }
        List<ColumnDataClickRate> dataClickRateList = dataClickRateMapper.selectRecent(columnDataIdList);
        Map<Integer, Integer> columnDataClickMap = dataClickRateList.stream().collect(Collectors.toMap(ColumnDataClickRate::getColumnDataId, ColumnDataClickRate::getClickRateTotal));
        columnDataList.forEach(columnData -> {
            Integer hitNumber = columnDataClickMap.get(columnData.getId());
            if (hitNumber == null) {
                columnData.setHitNumber(NumberConstant.NUMBER_0);
                return;
            }
            columnData.setHitNumber(hitNumber);
        });
    }

    private void handleColumnDataFilePlus(List<ColumnData> columnDataList, List<Integer> columnDataIdList) {
        if (CollectionUtils.isEmpty(columnDataIdList)) {
            return;
        }
        // 先查中间表
        LambdaQueryWrapper<FileRefColumnData> fileRefColumnDataLqw = new LambdaQueryWrapper<>();
        fileRefColumnDataLqw.in(FileRefColumnData::getColumnDataId, columnDataIdList);
        List<FileRefColumnData> fileRefColumnDataList = fileRefColumnDataMapper.selectList(fileRefColumnDataLqw);
        // 再查文件表
        if (CollectionUtils.isEmpty(fileRefColumnDataList)) {
            return;
        }
        List<File> fileList = fileMapper.selectBatchIds(fileRefColumnDataList.stream().map(FileRefColumnData::getFileId).collect(Collectors.toList()));
        // 获取文件,id是否需要去重
        // 中间表实体类根据数据id分组，文件集合则转为Map
        Map<Long, File> fileIdFileMap = fileList.stream().collect(Collectors.toMap(File::getId, file -> file));
        Map<Integer, List<FileRefColumnData>> dataIdFileRefDataMap = fileRefColumnDataList.stream()
                .collect(Collectors.groupingBy(FileRefColumnData::getColumnDataId, LinkedHashMap::new, Collectors.toList()));

        for (ColumnData data : columnDataList) {
            List<FileRefColumnData> fileRefColumnDataListForData = dataIdFileRefDataMap.get(data.getId());
            if (CollectionUtils.isEmpty(fileRefColumnDataListForData)) {
                continue;
            }
            subHandleColumnDataFileList(data, fileRefColumnDataListForData, fileIdFileMap);
        }
    }

    private LambdaQueryWrapper<ColumnRefColumnData> getColumnRefColumnDataLqw(Integer columnDataId) {
        LambdaQueryWrapper<ColumnRefColumnData> columnRefColumnDataLqw = new LambdaQueryWrapper<>();
        columnRefColumnDataLqw.eq(ColumnRefColumnData::getColumnDataId, columnDataId);
        return columnRefColumnDataLqw;
    }

    @Override
    public ResultVO<?> queryDataByColumnIdPage(ColumnDataPageVo columnDataPageVo) {
        columnDataPageVo.check();
        Integer columnId = columnDataPageVo.getColumnId();
        List<List<Integer>> tagId = columnDataPageVo.getTagId();
        Integer centerId = columnDataPageVo.getCenterId();
        String key;
        String last = StringPool.UNDERSCORE + columnDataPageVo.getCurrent() + StringPool.UNDERSCORE + columnDataPageVo.getSize();
        if (centerId != null) {
            key = REDIS_PREFIX + COLUMN_DATA_LIST_CENTER + columnId + StringPool.UNDERSCORE + centerId;
        } else if (!CollectionUtils.isEmpty(tagId)) {
            key = REDIS_PREFIX + COLUMN_DATA_LIST_TAG + columnId + StringPool.UNDERSCORE + tagId.get(0).get(0);
        } else {
            key = REDIS_PREFIX + COLUMN_DATA_LIST + columnId;
        }
        // 需要加上current和size
        key = key + last;
        String resultStr = JedisPoolFactory.select(key);
        if (resultStr != null) {
            return ResultVO.data(JSONObject.parseObject(resultStr));
        }

        ColumnType2 columnType2 = new ColumnType2();
        if (columnDataPageVo.getColumnType() == null) {
            Column column = columnMapper.selectById(columnId);
            columnDataPageVo.setColumnType(column.getColumnType());
        }
        // 只需要已发布的
        columnDataPageVo.setStatus(NumberConstant.NUMBER_1);
        LambdaQueryWrapper<ColumnData> columnDataLqw = new LambdaQueryWrapper<>();
        // 前台不需要全部字段
        IPage<ColumnData> columnDataIPage = getColumnDataIPage(columnDataPageVo, columnDataLqw, NumberConstant.NUMBER_1);

        List<ColumnData> columnDataList = columnDataIPage.getRecords();
        List<Integer> columnDataIdList = columnDataList.stream().map(ColumnData::getId).collect(Collectors.toList());
        // 1.处理文件
        handleColumnDataFilePlus(columnDataList, columnDataIdList);
        // 2.处理标签
        if (!CollectionUtils.isEmpty(tagId)) {
            handleColumnDataTagIdPlus(columnDataList, columnDataIdList);
        }
        columnType2.setData(columnDataIPage);

        JedisPoolFactory.setex(key, 30, JSONArray.toJSONString(columnType2, SerializerFeature.WriteDateUseDateFormat));
        return ResultVO.data(columnType2);
    }

    private void handleColumnDataTagIdPlus(List<ColumnData> columnDataList, List<Integer> columnDataIdList) {
        if (CollectionUtils.isEmpty(columnDataIdList)) {
            return;
        }
        LambdaQueryWrapper<ColumnDataRefMediaTag> dataRefMediaTagLqw = new LambdaQueryWrapper<>();
        dataRefMediaTagLqw.in(ColumnDataRefMediaTag::getColumnDataId, columnDataIdList);
        List<ColumnDataRefMediaTag> dataRefMediaTagList = refMediaTagMapper.selectList(dataRefMediaTagLqw);
        if (CollectionUtils.isEmpty(dataRefMediaTagList)) {
            // 为空则不需要继续
            return;
        }
        // 根据数据id分组,不需要注意顺序
        Map<Integer, List<ColumnDataRefMediaTag>> dataIdTagMap = dataRefMediaTagList.stream().collect(Collectors.groupingBy(ColumnDataRefMediaTag::getColumnDataId));
        columnDataList.forEach(data -> {
            List<ColumnDataRefMediaTag> dataRefMediaTagListForData = dataIdTagMap.get(data.getId());
            if (CollectionUtils.isEmpty(dataRefMediaTagListForData)) {
                return;
            }
            List<List<Integer>> tagId = new ArrayList<>(dataRefMediaTagListForData.size());
            dataRefMediaTagListForData.forEach(dataRefMediaTag -> {
                List<Integer> tagArray = new ArrayList<>(NumberConstant.NUMBER_2);
                tagArray.add(dataRefMediaTag.getMediaTagGroupId());
                tagArray.add(dataRefMediaTag.getMediaTagId());
                tagId.add(tagArray);
            });
            data.setTagId(tagId);
        });
    }

    private IPage<ColumnData> getColumnDataIPage(ColumnDataPageVo columnDataPageVo, LambdaQueryWrapper<ColumnData> columnDataLqw, Integer orderStatus) {
        IPage<ColumnData> page = new Page<>(columnDataPageVo.getCurrent(), columnDataPageVo.getSize());
        Integer columnType = columnDataPageVo.getColumnType();
        // IPage<ColumnData> columnDataIPage;
        // 是否为首页栏目
        if (Objects.equals(columnType, 3) || Objects.equals(columnType, 5)) {
            // 需要先查中间表
            List<ColumnRefColumnData> columnRefColumnDataList = getColumnRefColumnDataList(columnDataPageVo);
            List<Integer> columnDataIdList = columnRefColumnDataList.stream().map(ColumnRefColumnData::getColumnDataId).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(columnDataIdList)) {
                return page;
            }
            columnDataLqw.in(ColumnData::getId, columnDataIdList);
            // 2.其他筛选条件
            preQueryColumnData(columnDataLqw, columnDataPageVo);
            // 3.排序,orderStatus为0则为后台,需要手动分页，为1则为前台
            if (orderStatus == NumberConstant.NUMBER_0) {
                List<ColumnData> columnDataList = columnDataMapper.selectList(columnDataLqw);
                Map<Integer, ColumnData> dataIdDataMap = columnDataList.stream().collect(Collectors.toMap(ColumnData::getId, columnData -> columnData));
                List<ColumnData> columnDataListForReturn = columnRefColumnDataList.stream().map(columnRefColumnData -> {
                    ColumnData columnData = dataIdDataMap.get(columnRefColumnData.getColumnDataId());
                    if (columnData == null) {
                        return null;
                    }
                    columnData.setRefColumnDataId(columnRefColumnData.getId());
                    return columnData;
                }).filter(Objects::nonNull).collect(Collectors.toList());
                // 分页
                return PageUtil.getPages((int) page.getCurrent(), (int) page.getSize(), columnDataListForReturn);
            }
            handleOrder(columnDataLqw, orderStatus, columnType);
            return columnDataMapper.selectPage(page, columnDataLqw);
        }
        columnDataLqw.eq(ColumnData::getColumnId, columnDataPageVo.getColumnId());
        // 2.其他筛选条件
        preQueryColumnData(columnDataLqw, columnDataPageVo);
        // 3.排序
        handleOrder(columnDataLqw, orderStatus, columnType);
        return columnDataMapper.selectPage(page, columnDataLqw);
    }

    // 排序,orderStatus为0表示后台，根据排序数排序，为1则为前台，根据栏目类型选择排序字段
    private void handleOrder(LambdaQueryWrapper<ColumnData> columnDataLqw, Integer orderStatus, Integer columnType) {
        if (Objects.equals(orderStatus, NumberConstant.NUMBER_0)) {
            columnDataLqw.orderByDesc(ColumnData::getOrderNum);
        }else {
            if (Objects.equals(columnType, NumberConstant.NUMBER_1)) {
                // 栏目数据根据排序数来排序
                columnDataLqw.orderByDesc(ColumnData::getOrderNum);
            } else {
                // 稿件数据根据发布时间来排序
                columnDataLqw.orderByDesc(ColumnData::getPublishTime);
            }
        }
    }

    private void preQueryColumnData(LambdaQueryWrapper<ColumnData> columnDataLqw, ColumnDataPageVo columnDataPageVo) {
        // 状态
        columnDataLqw.eq(Objects.nonNull(columnDataPageVo.getStatus()), ColumnData::getStatus, columnDataPageVo.getStatus());
        // 组织或协会
        columnDataLqw.eq(Objects.nonNull(columnDataPageVo.getCenterId()), ColumnData::getCenterId, columnDataPageVo.getCenterId());
        // 发布时间
        columnDataLqw.ge(Objects.nonNull(columnDataPageVo.getBeginDate()), ColumnData::getPublishTime, columnDataPageVo.getBeginDate());
        columnDataLqw.le(Objects.nonNull(columnDataPageVo.getEndDate()), ColumnData::getPublishTime, columnDataPageVo.getEndDate());
        // 稿件id
        columnDataLqw.eq(Objects.nonNull(columnDataPageVo.getId()), ColumnData::getId, columnDataPageVo.getId());
        // 创建人
        columnDataLqw.like(StringUtils.isNotBlank(columnDataPageVo.getCreatedBy()), ColumnData::getCreatedBy, columnDataPageVo.getCreatedBy());
        // 标题
        columnDataLqw.like(StringUtils.isNotBlank(columnDataPageVo.getTitle()), ColumnData::getTitle, columnDataPageVo.getTitle());
        // 标签
        if (!CollectionUtils.isEmpty(columnDataPageVo.getTagId())) {
            List<List<Integer>> tagId = columnDataPageVo.getTagId();
            Integer mediaTagId = tagId.get(0).get(0);
            // 为0则不需要拼接任何条件
            if (mediaTagId != NumberConstant.NUMBER_0) {
                LambdaQueryWrapper<ColumnDataRefMediaTag> dataRefMediaTagLqw = new LambdaQueryWrapper<>();
                // 只需要查columnDataId
                dataRefMediaTagLqw.select(ColumnDataRefMediaTag::getColumnDataId);
                dataRefMediaTagLqw.eq(ColumnDataRefMediaTag::getMediaTagId, mediaTagId);
                List<ColumnDataRefMediaTag> columnDataRefMediaTags = refMediaTagMapper.selectList(dataRefMediaTagLqw);
                List<Integer> columnDataIdList = columnDataRefMediaTags.stream().map(ColumnDataRefMediaTag::getColumnDataId).collect(Collectors.toList());
                // 不为空才需要拼接,为空则拼接查询不到结果的条件,为0则返回所有结果
                if (!CollectionUtils.isEmpty(columnDataIdList)) {
                    columnDataLqw.in(ColumnData::getId, columnDataIdList);
                } else {
                    columnDataLqw.eq(ColumnData::getId, NumberConstant.NUMBER_0);
                }
            }
        }
    }

    private LambdaQueryWrapper<ColumnDataRefMediaTag> getColumnDataRefMediaTagLqw(Integer columnDataId) {
        LambdaQueryWrapper<ColumnDataRefMediaTag> refMediaTagLqw = new LambdaQueryWrapper<>();
        refMediaTagLqw.eq(ColumnDataRefMediaTag::getColumnDataId, columnDataId);
        return refMediaTagLqw;
    }

    private LambdaQueryWrapper<FileRefColumnData> getFileRefColumnDataLqw(Integer columnDataId) {
        LambdaQueryWrapper<FileRefColumnData> fileRefColumnDataLqw = new LambdaQueryWrapper<>();
        fileRefColumnDataLqw.eq(FileRefColumnData::getColumnDataId, columnDataId);
        return fileRefColumnDataLqw;
    }

    @Override
    @Transactional
    public ResultVO updateData(ColumnData columnData) {
        Integer columnDataId = columnData.getId();
        ColumnData columnDataForJudging = columnDataMapper.selectById(columnDataId);
        if (columnDataForJudging == null) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        String title = columnData.getTitle();
        Integer columnId = columnData.getColumnId();
        if (StringUtils.isNotBlank(title) && !title.equals(columnDataForJudging.getTitle()) && columnId != null) {
            // 标题不为空且修改时要判断同栏目下是否已经存在
            List<ColumnData> columnDataList = getColumnDataList(title, columnId);
            if (columnDataList.size() > 0) {
                return ResultVO.fail("该标题已经存在");
            }
        }

        columnDataMapper.update(null, getColumnDataLuw(columnData));
        // List<Long> fileIdList = columnData.getFileIdList();
        List<List<Integer>> tagId = columnData.getTagId();
        // 1.修改文件,先删
        fileRefColumnDataMapper.delete(getFileRefColumnDataLqw(columnDataId));
        // 后增
        List<FileRefColumnData> fileRefColumnDataList;
        try {
            fileRefColumnDataList = getFileRefColumnDataPlus(columnData);
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.error("修改栏目数据发生异常：" + e);
            return ResultVO.fail(e.getMessage());
        }
        if (!CollectionUtils.isEmpty(fileRefColumnDataList)) {
            fileRefColumnDataMapper.insertBatch(fileRefColumnDataList);
        }
        // 2.修改标签,先删
        refMediaTagMapper.delete(getColumnDataRefMediaTagLqw(columnDataId));
        // 后增
        if (!CollectionUtils.isEmpty(tagId)) {
            // tagId不为空才需要以下操作
            List<ColumnDataRefMediaTag> columnDataRefMediaTagList;
            try {
                columnDataRefMediaTagList = getColumnDataRefMediaTagList(columnData.getId(), tagId);
            } catch (Exception e) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                log.error("修改栏目数据发生异常：" + e.getMessage());
                return ResultVO.fail(ResultCode.SERVE_ERROR);
            }
            refMediaTagMapper.insertBatch(columnDataRefMediaTagList);
        }
        return ResultVO.success(ResultCode.SUCCESS);
    }

    private LambdaUpdateWrapper<ColumnData> getColumnDataLuw(ColumnData columnData) {
        LambdaUpdateWrapper<ColumnData> dataLuw = new LambdaUpdateWrapper<>();
        dataLuw.eq(ColumnData::getId, columnData.getId()).set(ColumnData::getGmtUpdated, new Date());
        dataLuw.set(Objects.nonNull(columnData.getPersonName()), ColumnData::getPersonName, columnData.getPersonName());
        dataLuw.set(Objects.nonNull(columnData.getJob()), ColumnData::getJob, columnData.getJob());
        dataLuw.set(Objects.nonNull(columnData.getIntroduce()), ColumnData::getIntroduce, columnData.getIntroduce());
        dataLuw.set(Objects.nonNull(columnData.getImgAddress()), ColumnData::getImgAddress, columnData.getImgAddress());
        dataLuw.set(Objects.nonNull(columnData.getTitle()), ColumnData::getTitle, columnData.getTitle());
        dataLuw.set(Objects.nonNull(columnData.getSubheading()), ColumnData::getSubheading, columnData.getSubheading());

        dataLuw.set(Objects.nonNull(columnData.getCenterId()), ColumnData::getCenterId, columnData.getCenterId());
        dataLuw.set(Objects.nonNull(columnData.getJumpOrNot()), ColumnData::getJumpOrNot, columnData.getJumpOrNot());
        dataLuw.set(Objects.nonNull(columnData.getContentAbstract()), ColumnData::getContentAbstract, columnData.getContentAbstract());
        dataLuw.set(Objects.nonNull(columnData.getCover()), ColumnData::getCover, columnData.getCover());
        return dataLuw;
    }

    @Override
    public ResultVO queryDataById(Integer id) {
        // 需要记录点击量
        countQuery(id);
        // 查缓存
        String resultStr = JedisPoolFactory.select(REDIS_PREFIX + COLUMN_DATA + id);
        if (resultStr != null) {
            return ResultVO.data(JSONObject.parseObject(resultStr));
        }
        ColumnData columnData = columnDataMapper.selectById(id);
        if (columnData == null) {
            return ResultVO.fail("该数据已被删除");
        }
        handleColumnDataFiles(columnData);
        // 存缓存,这个缓存在什么时候删？
        JedisPoolFactory.setex(REDIS_PREFIX + COLUMN_DATA + id, 30, JSONArray.toJSONString(columnData, SerializerFeature.WriteDateUseDateFormat));
        return ResultVO.data(columnData);
    }

    private void handleColumnDataFiles(ColumnData data) {
        // 查询文件
        List<FileRefColumnData> fileRefColumnDataList = fileRefColumnDataMapper.selectList(getFileRefColumnDataLqw(data.getId()));
        if (!CollectionUtils.isEmpty(fileRefColumnDataList)) {
            // 有对应文件则继续
            List<File> fileList = fileMapper.selectBatchIds(fileRefColumnDataList.stream().map(FileRefColumnData::getFileId).collect(Collectors.toList()));
            Map<Long, File> idFileMap = fileList.stream().collect(Collectors.toMap(File::getId, file -> file));
            subHandleColumnDataFileList(data, fileRefColumnDataList, idFileMap);
        }
    }

    private void subHandleColumnDataFileList(ColumnData data, List<FileRefColumnData> fileRefColumnDataList, Map<Long, File> idFileMap) {
        // 根据文件类型分组
        Map<Integer, List<FileRefColumnData>> fileTypeFileListMap = fileRefColumnDataList.stream()
                .collect(Collectors.groupingBy(FileRefColumnData::getFileType, LinkedHashMap::new, Collectors.toList()));
        List<File>[] fileArray = new List[4];
        for (int i = 0; i < 4; i++) {
            List<FileRefColumnData> fileRefColumnDataListTemp = fileTypeFileListMap.get(i);
            if (CollectionUtils.isEmpty(fileRefColumnDataListTemp)) {
                fileArray[i] = Collections.emptyList();
                continue;
            }
            // 文件不会被删除，即使被删除也没有空指针的风险
            fileArray[i] = fileRefColumnDataListTemp.stream().map(fileRefColumnData -> idFileMap.get(fileRefColumnData.getFileId())).collect(Collectors.toList());
        }
        // 赋值
        data.setUploadImg(fileArray[NumberConstant.NUMBER_0]);
        data.setUploadVideo(fileArray[NumberConstant.NUMBER_1]);
        data.setAttachment(fileArray[NumberConstant.NUMBER_2]);
        data.setFile(fileArray[NumberConstant.NUMBER_3]);
    }

    private void countQuery(Integer id) {
        JedisPoolFactory.incr(REDIS_PREFIX + COLUMN_DATA_CLICK + id);
    }

    @Override
    @Transactional
    public ResultVO updateColumn(ColumnSaveVo columnSaveVo) {
        Integer columnId = columnSaveVo.getColumnId();
        if (columnId == null) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        Column column = columnMapper.selectById(columnId);
        if (column == null) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        LambdaUpdateWrapper<Column> columnLuw = new LambdaUpdateWrapper<>();
        columnLuw.eq(Column::getId, columnId);
        // 修改中文名英文名
        columnLuw.set(Objects.nonNull(columnSaveVo.getColumnName()), Column::getColumnName, columnSaveVo.getColumnName());
        columnLuw.set(Objects.nonNull(columnSaveVo.getEnName()), Column::getEnName, columnSaveVo.getEnName());
        // 修改栏目介绍?
        columnMapper.update(null, columnLuw);
        List<Integer> componentIdList = columnSaveVo.getComponentIdList();
        // 组件需要修改时，先删后增
        LambdaQueryWrapper<ColumnRefComponent> refComponentLqw = new LambdaQueryWrapper<>();
        refComponentLqw.eq(ColumnRefComponent::getColumnId, columnId);
        refComponentMapper.delete(refComponentLqw);
        if (!CollectionUtils.isEmpty(componentIdList)) {
            // 不为空才需要这一步
            List<ColumnRefComponent> columnRefComponentList = getColumnRefComponentList(componentIdList, columnId);
            refComponentMapper.insertBatch(columnRefComponentList);
        }
        return ResultVO.success(ResultCode.SUCCESS);
    }

    @Override
    // @Transactional
    public ResultVO upOrDown(ColumnData columnData) {
        Integer id = columnData.getId();
        Integer status = columnData.getStatus();
        Long orderNum = columnData.getOrderNum();
        if (status != null) {
            // 发布与下线
            LambdaUpdateWrapper<ColumnData> dataLuw = new LambdaUpdateWrapper<>();
            dataLuw.eq(ColumnData::getId, id);
            dataLuw.set(Objects.nonNull(columnData.getStatus()), ColumnData::getStatus, status);
            if (status == 1) {
                // 发布需要更新发布时间和排序数
                Date publishTime = columnData.getPublishTime();
                if (publishTime == null) {
                    dataLuw.set(ColumnData::getPublishTime, new Date()).set(ColumnData::getOrderNum, System.currentTimeMillis());
                } else {
                    // 发布时间可手动选择
                    dataLuw.set(ColumnData::getPublishTime, publishTime).set(ColumnData::getOrderNum, publishTime.getTime());
                }
            }
            columnDataMapper.update(null, dataLuw);

            // 目前只有发布和下线需要清除被推荐栏目的缓存
            List<Integer> refColumnIdList = columnData.getRefColumnIdList();
            if (!CollectionUtils.isEmpty(refColumnIdList)) {
                for (int i = 0; i < refColumnIdList.size(); i++) {
                    JedisPoolFactory.scanAndDel(REDIS_PREFIX + COLUMN_DATA_LIST + refColumnIdList.get(i));
                }
            }
        }
        if (orderNum != null) {
            ColumnData columnDataWaiting = columnDataMapper.selectById(id);
            Integer columnId = columnDataWaiting.getColumnId();
            LambdaQueryWrapper<ColumnData> columnDataLqw = new LambdaQueryWrapper<>();
            columnDataLqw.eq(ColumnData::getColumnId, columnId);
            if (orderNum == NumberConstant.NUMBER_1) {
                // 上移，查询同一栏目上一条数据
                orderNum = columnDataWaiting.getOrderNum();
                columnDataLqw.gt(ColumnData::getOrderNum, orderNum).orderByAsc(ColumnData::getOrderNum);
            } else {
                // 下移，查询下一条数据
                orderNum = columnDataWaiting.getOrderNum();
                columnDataLqw.lt(ColumnData::getOrderNum, orderNum).orderByDesc(ColumnData::getOrderNum);
            }
            columnDataLqw.last("limit " + NumberConstant.NUMBER_1);
            ColumnData columnDataWaitingUpdating;

            columnDataWaitingUpdating = columnDataMapper.selectOne(columnDataLqw);
            if (columnDataWaitingUpdating == null) {
                return ResultVO.fail("该数据无法上移/下移");
            }
            // 排序数互换
            exchangeOrderNum(id, columnDataWaitingUpdating.getOrderNum());
            exchangeOrderNum(columnDataWaitingUpdating.getId(), orderNum);
        }

        // 用于清除缓存
        Integer columnIdForDelete = columnData.getColumnId();
        // 普通的缓存
        if (columnIdForDelete != null) {
            JedisPoolFactory.scanAndDel(REDIS_PREFIX + COLUMN_DATA_LIST + columnIdForDelete);
        }
        return ResultVO.success(ResultCode.SUCCESS);
    }

    private void exchangeOrderNum(Integer id, Long orderNum) {
        LambdaUpdateWrapper<ColumnData> columnDataLuw = new LambdaUpdateWrapper<>();
        columnDataLuw.eq(ColumnData::getId, id).set(ColumnData::getOrderNum, orderNum);
        columnDataMapper.update(null, columnDataLuw);
    }

    @Override
    @Transactional
    public ResultVO hideDataById(Integer id) {
        columnDataMapper.deleteById(id);
        // 引用该数据的表记录要删除
        refColumnDataMapper.delete(getColumnRefColumnDataLqw(id));
        // 标签中间表删除
        refMediaTagMapper.delete(getColumnDataRefMediaTagLqw(id));
        // todo 文件中间表删除
        return ResultVO.success(ResultCode.SUCCESS);
    }

    /**
     * 分词查询稿件
     *
     * @param websiteId   网站id
     * @param content     搜索内容
     * @param current     当前页
     * @param size        每页显示数量
     * @param timeRange   时间范围 0所有 1一周内 2一月内 3一年内
     * @param searchRange 搜索范围 0所有 1标题 2正文
     * @return 搜索结果
     */
    @Override
    public ResultVO search(String websiteId, String content, Integer current, Integer size, Integer timeRange, Integer searchRange) {
        //1.直接按搜索内容查找
        IPage<ColumnData> page = new Page<>(current, size);

        if (current < 0 || size <= 0 || StringUtils.isBlank(content)) {
            page.setRecords(Collections.emptyList());
            page.setTotal(0);
            return ResultVO.data(page);
        }
        try {
            page = columnDataMapper.selectPage(page, getWebContents(websiteId, content, timeRange, searchRange));
            if (page.getTotal() > 0) return ResultVO.data(page);

            //2.第一步查找失败变为分词查找
            Map<String, Object> params = new HashMap<>();
            params.put("text", content);
            ResultVO<?> resultVO = algorithmClient.chineseSegment(new JSONObject(params).toJSONString());
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(resultVO));
            List<String> participles = JSONObject.parseObject(jsonObject.getString("data"), new TypeReference<List<String>>() {
            });
            if (CollectionUtils.isEmpty(participles)) return ResultVO.data(page);

            CountDownLatch countDownLatch = new CountDownLatch(participles.size());
            List<FutureTask<List<ColumnData>>> futureTasks = new ArrayList<>(participles.size());
            participles.forEach(p -> {
                FutureTask<List<ColumnData>> futureTask = new FutureTask<>(new SearchTask(countDownLatch, p, websiteId, timeRange, searchRange));
                GlobalThreadPoolExecutor.poolExecutor.submit(futureTask);
                futureTasks.add(futureTask);
            });

            countDownLatch.await(10, TimeUnit.SECONDS);

            //多线程查找结果聚合
            Set<ColumnData> ColumnDataList = new HashSet<>();

            for (FutureTask<List<ColumnData>> futureTask : futureTasks) {
                ColumnDataList.addAll(futureTask.get());
            }

            int s = Math.min((current - 1) * size, ColumnDataList.size());
            int e = Math.min(s + size, ColumnDataList.size());
            List<ColumnData> participleResult = ColumnDataList.stream().sorted(Comparator.comparing(ColumnData::getId)).collect(Collectors.toList()).subList(s, e);
            page.setRecords(participleResult);
            page.setTotal(participleResult.size());
        } catch (Exception e) {
            log.error("稿件搜索失败{},原因:{}", content, e.getMessage());
            return ResultVO.data(ResultCode.FAILURE.getCode(), page, ResultCode.FAILURE.getMessage());
        }

        return ResultVO.data(page);
    }

    private LambdaQueryWrapper<ColumnData> getWebContents(String websiteId, String content, Integer timeRange, Integer searchRange) {
        if (Objects.isNull(websiteId)) websiteId = "1";
        LambdaQueryWrapper<ColumnData> queryWrapper = new LambdaQueryWrapper<>();
        // 不需要这个条件了
        // queryWrapper.eq("website_id", websiteId);
        queryWrapper.eq(ColumnData::getStatus, NumberConstant.NUMBER_1);
        // queryWrapper.notLike("path", "之江景");
        preQueryColumnData(websiteId, queryWrapper);

        queryWrapper.orderByDesc(ColumnData::getPublishTime);

        if (StringUtils.isNotBlank(content)) getSearchRange(queryWrapper, searchRange, content);

        getTimeRange(queryWrapper, timeRange);


        return queryWrapper;
    }

    private void preQueryColumnData(String websiteId, LambdaQueryWrapper<ColumnData> queryWrapper) {
        // 只需要查各个网站columnType为2的栏目
        // 首先查该网站有哪些模块
        List<Integer> moudleIdList = moudleMapper.queryMoudleByWebsiteIdPlus(Integer.valueOf(websiteId));
        // 再查这些模块下有哪些columnType为2的栏目的id
        if (CollectionUtils.isEmpty(moudleIdList)) {
            queryWrapper.eq(ColumnData::getColumnId, NumberConstant.NUMBER_0);
            return;
        }
        LambdaQueryWrapper<Column> columnLqw = new LambdaQueryWrapper<>();
        // 只需要查id
        columnLqw.select(Column::getId);
        columnLqw.in(Column::getMoudleId, moudleIdList);
        columnLqw.eq(Column::getColumnType, NumberConstant.NUMBER_2);
        List<Column> columnList = columnMapper.selectList(columnLqw);
        List<Integer> columnIdList = columnList.stream().map(Column::getId).collect(Collectors.toList());
        // 拼接条件
        if (CollectionUtils.isEmpty(columnIdList)) {
            queryWrapper.eq(ColumnData::getColumnId, NumberConstant.NUMBER_0);
            return;
        }
        queryWrapper.in(ColumnData::getColumnId, columnIdList);
    }

    private static void getSearchRange(LambdaQueryWrapper<ColumnData> queryWrapper, Integer searchRange, String content) {
        switch (searchRange) {
            case 1:
                queryWrapper.like(ColumnData::getTitle, content);
                break;
            case 2:
                queryWrapper.like(ColumnData::getOriginalContent, content);
                break;
            default:
                queryWrapper.and(qw -> qw.like(ColumnData::getTitle, content).or().like(ColumnData::getContentAbstract, content).or().like(ColumnData::getOriginalContent, content));
                break;
        }
    }

    private static void getTimeRange(LambdaQueryWrapper<ColumnData> queryWrapper, Integer timeRange) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date currentDate = new Date();
        String sDate = format.format(currentDate);
        Calendar c = Calendar.getInstance();
        c.setTime(currentDate);

        switch (timeRange) {
            case 1://一周内
                c.add(Calendar.DATE, -7);
                break;
            case 2://一月内
                c.add(Calendar.MONTH, -1);
                break;
            case 3://一年内
                c.add(Calendar.YEAR, -1);
                break;
            default:
                return;
        }

        String eDate = format.format(c.getTime());

        queryWrapper.le(ColumnData::getPublishTime, sDate);
        queryWrapper.ge(ColumnData::getPublishTime, eDate);
    }

    class SearchTask implements Callable<List<ColumnData>> {

        private final CountDownLatch countDownLatch;

        private final String content;
        private final String websiteId;
        private final Integer timeRange;
        private final Integer searchRange;
        public SearchTask(CountDownLatch countDownLatch, String content, String websiteId, Integer timeRange, Integer searchRange) {
            this.countDownLatch = countDownLatch;
            this.content = content;
            this.websiteId = websiteId;
            this.timeRange = timeRange;
            this.searchRange = searchRange;
        }

        @Override
        public List<ColumnData> call() {
            try {
                return columnDataMapper.selectList(getWebContents(websiteId, content, timeRange, searchRange));
            } catch (Exception e) {
                log.error("稿件分词搜索失败{}", content);
            } finally {
                countDownLatch.countDown();
            }
            return Collections.emptyList();
        }

    }

    @Override
    public ResultVO generate(ModuleColumnGeneratorVo generatorVo) {
        Integer templateId = generatorVo.getTemplateId();
        Integer websiteId = generatorVo.getWebsiteId();
        if (templateId == null || websiteId == null) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        // 1.查询模块、栏目、组件模板
        LambdaQueryWrapper<ModuleTemplate> moduleTemplateLqw = new LambdaQueryWrapper<ModuleTemplate>().eq(ModuleTemplate::getTemplateId, templateId);
        LambdaQueryWrapper<ColumnTemplate> columnTemplateLqw = new LambdaQueryWrapper<ColumnTemplate>().eq(ColumnTemplate::getTemplateId, templateId);
        LambdaQueryWrapper<ColumnRefComPlate> columnRefComPlateLqw = new LambdaQueryWrapper<ColumnRefComPlate>().eq(ColumnRefComPlate::getTemplateId, templateId);
        List<ModuleTemplate> moduleTemplateList = moduleTemplateMapper.selectList(moduleTemplateLqw);
        List<ColumnTemplate> columnTemplateList = columnTemplateMapper.selectList(columnTemplateLqw);
        List<ColumnRefComPlate> columnRefComPlateList = comPlateMapper.selectList(columnRefComPlateLqw);
        // 2.组装
        Date date = new Date();
        // 2.1.处理模块
        Map<Integer, Moudle> tmIdModuleMap = new HashMap<>(moduleTemplateList.size());
        List<Moudle> moduleList = moduleTemplateList.stream().map(moduleTemplate -> {
            Moudle moudle = new Moudle();
            tmIdModuleMap.put(moduleTemplate.getId(), moudle);
            BeanUtils.copyProperties(moduleTemplate, moudle);
            moudle.setWebsiteId(websiteId);
            moudle.setId(null);
            moudle.setGmtCreated(date);
            return moudle;
        }).collect(Collectors.toList());
        moudleMapper.insertBatchSomeColumn(moduleList);
        // 修改父id
        Map<Integer, List<Moudle>> pidModuleMap = moduleList.stream().collect(Collectors.groupingBy(Moudle::getParentId));
        for (Map.Entry<Integer, List<Moudle>> integerListEntry : pidModuleMap.entrySet()) {
            Integer parentId = integerListEntry.getKey();
            if (parentId == NumberConstant.NUMBER_0) {
                continue;
            }
            List<Integer> moduleIdListForUpdate = integerListEntry.getValue().stream().map(Moudle::getId).collect(Collectors.toList());
            LambdaUpdateWrapper<Moudle> moudleLuw = new LambdaUpdateWrapper<>();
            moudleLuw.in(Moudle::getId, moduleIdListForUpdate);
            moudleLuw.set(Moudle::getParentId, tmIdModuleMap.get(parentId).getId());
            moudleMapper.update(null, moudleLuw);
        }
        // 2.2.处理栏目
        Map<Integer, Column> tcIdColumnMap = new HashMap<>(columnTemplateList.size());
        List<Column> columnList = columnTemplateList.stream().map(columnTemplate -> {
            Column column = new Column();
            tcIdColumnMap.put(columnTemplate.getId(), column);
            BeanUtils.copyProperties(columnTemplate, column);
            column.setMoudleId(tmIdModuleMap.get(columnTemplate.getMoudleId()).getId());
            column.setId(null);
            column.setGmtCreated(date);
            return column;
        }).collect(Collectors.toList());
        columnMapper.insertBatchSomeColumn(columnList);
        // 2.3.处理组件
        List<ColumnRefComponent> columnRefComponentList = columnRefComPlateList.stream().map(columnRefComPlate -> {
            ColumnRefComponent columnRefComponent = new ColumnRefComponent();
            BeanUtils.copyProperties(columnRefComPlate, columnRefComponent);
            columnRefComponent.setColumnId(tcIdColumnMap.get(columnRefComPlate.getColumnId()).getId());
            columnRefComponent.setId(null);
            return columnRefComponent;
        }).collect(Collectors.toList());
        refComponentMapper.insertBatch(columnRefComponentList);
        return ResultVO.success(ResultCode.SUCCESS);
    }

    @Override
    public ResultVO temp(ModuleColumnGeneratorVo generatorVo) {
        // Integer templateId = generatorVo.getTemplateId();
        Integer websiteId = NumberConstant.NUMBER_2;
        // 1.查询模块、栏目、组件模板
        List<Moudle> moduleTemplateList = moudleMapper.selectList(new LambdaQueryWrapper<Moudle>().eq(Moudle::getWebsiteId, websiteId));
        List<Integer> moduleIdList = moduleTemplateList.stream().map(Moudle::getId).collect(Collectors.toList());
        List<Column> columnTemplateList = columnMapper.selectList(new LambdaQueryWrapper<Column>().in(Column::getMoudleId, moduleIdList));
        List<Integer> columnIdList = columnTemplateList.stream().map(Column::getId).collect(Collectors.toList());
        List<ColumnRefComponent> columnRefComPlateList = refComponentMapper.selectList(
                new LambdaQueryWrapper<ColumnRefComponent>().in(ColumnRefComponent::getColumnId, columnIdList));
        // 2.组装
        Date date = new Date();
        // 2.1.处理模块
        Map<Integer, Moudle> tmIdModuleMap = new HashMap<>(moduleTemplateList.size());
        Integer finalWebsiteId = NumberConstant.NUMBER_3;
        List<Moudle> moduleList = moduleTemplateList.stream().map(moduleTemplate -> {
            Moudle moudle = new Moudle();
            tmIdModuleMap.put(moduleTemplate.getId(), moudle);
            BeanUtils.copyProperties(moduleTemplate, moudle);
            moudle.setWebsiteId(finalWebsiteId);
            moudle.setId(null);
            // moudle.setIsDeleted(NumberConstant.NUMBER_0);
            moudle.setGmtCreated(date);
            return moudle;
        }).collect(Collectors.toList());
        moudleMapper.insertBatchSomeColumn(moduleList);
        // 修改父id
        Map<Integer, List<Moudle>> pidModuleMap = moduleList.stream().collect(Collectors.groupingBy(Moudle::getParentId));
        for (Map.Entry<Integer, List<Moudle>> integerListEntry : pidModuleMap.entrySet()) {
            Integer parentId = integerListEntry.getKey();
            if (parentId == NumberConstant.NUMBER_0) {
                continue;
            }
            List<Integer> moduleIdListForUpdate = integerListEntry.getValue().stream().map(Moudle::getId).collect(Collectors.toList());
            LambdaUpdateWrapper<Moudle> moudleLuw = new LambdaUpdateWrapper<>();
            moudleLuw.in(Moudle::getId, moduleIdListForUpdate);
            moudleLuw.set(Moudle::getParentId, tmIdModuleMap.get(parentId).getId());
            moudleMapper.update(null, moudleLuw);
        }
        // 2.2.处理栏目
        Map<Integer, Column> tcIdColumnMap = new HashMap<>(columnTemplateList.size());
        List<Column> columnList = columnTemplateList.stream().map(columnTemplate -> {
            Column column = new Column();
            tcIdColumnMap.put(columnTemplate.getId(), column);
            BeanUtils.copyProperties(columnTemplate, column);
            column.setMoudleId(tmIdModuleMap.get(columnTemplate.getMoudleId()).getId());
            column.setId(null);
            // column.setIsDeleted(NumberConstant.NUMBER_0);
            column.setGmtCreated(date);
            return column;
        }).collect(Collectors.toList());
        // columnMapper.insertBatch(columnList);
        columnMapper.insertBatchSomeColumn(columnList);
        // 2.3.处理组件
        List<ColumnRefComponent> columnRefComponentList = columnRefComPlateList.stream().map(columnRefComPlate -> {
            ColumnRefComponent columnRefComponent = new ColumnRefComponent();
            BeanUtils.copyProperties(columnRefComPlate, columnRefComponent);
            columnRefComponent.setColumnId(tcIdColumnMap.get(columnRefComPlate.getColumnId()).getId());
            columnRefComponent.setId(null);
            return columnRefComponent;
        }).collect(Collectors.toList());
        refComponentMapper.insertBatch(columnRefComponentList);
        return ResultVO.success(ResultCode.SUCCESS);
    }

    @Override
    public ResultVO reserveTemp(ModuleColumnGeneratorVo generatorVo) {
        Integer templateId = generatorVo.getTemplateId();
        Integer websiteId = generatorVo.getWebsiteId();
        // 2.分別查出模塊、欄目、組件
        List<Moudle> moudleList = moudleMapper.selectList(new LambdaQueryWrapper<Moudle>().eq(Moudle::getWebsiteId, websiteId));
        List<Integer> moduleIds = moudleList.stream().map(Moudle::getId).collect(Collectors.toList());
        List<Column> columnList = columnMapper.selectList(new LambdaQueryWrapper<Column>().in(Column::getMoudleId, moduleIds));
        List<Integer> columnIds = columnList.stream().map(Column::getId).collect(Collectors.toList());
        List<ColumnRefComponent> refComponentList = refComponentMapper.selectList(new LambdaQueryWrapper<ColumnRefComponent>().in(ColumnRefComponent::getColumnId, columnIds));
        // 3.組裝，插入
        Map<Integer, ModuleTemplate> midModuleTempMap = new HashMap<>(moduleIds.size());
        Map<Integer, ColumnTemplate> cidColumnTempMap = new HashMap<>(columnIds.size());
        List<ModuleTemplate> moduleTemplateList = moudleList.stream().map(moudle -> {
            ModuleTemplate moduleTemplate = new ModuleTemplate();
            midModuleTempMap.put(moudle.getId(), moduleTemplate);
            BeanUtils.copyProperties(moudle, moduleTemplate);
            moduleTemplate.setId(null);
            moduleTemplate.setTemplateId(templateId);
            return moduleTemplate;
        }).collect(Collectors.toList());
        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        try {
            // 先刪除
            moduleTemplateMapper.delete(new LambdaQueryWrapper<ModuleTemplate>().eq(ModuleTemplate::getTemplateId, templateId));
            columnTemplateMapper.delete(new LambdaQueryWrapper<ColumnTemplate>().eq(ColumnTemplate::getTemplateId, templateId));
            comPlateMapper.delete(new LambdaQueryWrapper<ColumnRefComPlate>().eq(ColumnRefComPlate::getTemplateId, templateId));
            // 再插入
            moduleTemplateMapper.insertBatchSomeColumn(moduleTemplateList);
            // 模塊插入後修改父id
            Map<Integer, List<ModuleTemplate>> pidModuleTempMap = moduleTemplateList.stream().collect(Collectors.groupingBy(ModuleTemplate::getParentId));
            pidModuleTempMap.forEach((pid, moduleTemplates) -> {
                if (pid == NumberConstant.NUMBER_0) {
                    return;
                }
                List<Integer> moduleTempIds = moduleTemplates.stream().map(ModuleTemplate::getId).collect(Collectors.toList());
                LambdaUpdateWrapper<ModuleTemplate> moduleTemplateLuw = new LambdaUpdateWrapper<>();
                moduleTemplateLuw.in(ModuleTemplate::getId, moduleTempIds).set(ModuleTemplate::getParentId, midModuleTempMap.get(pid).getId());
                moduleTemplateMapper.update(null, moduleTemplateLuw);
            });
            List<ColumnTemplate> columnTemplateList = columnList.stream().map(column -> {
                ColumnTemplate columnTemplate = new ColumnTemplate();
                cidColumnTempMap.put(column.getId(), columnTemplate);
                BeanUtils.copyProperties(column, columnTemplate);
                columnTemplate.setId(null);
                columnTemplate.setTemplateId(templateId);
                columnTemplate.setMoudleId(midModuleTempMap.get(column.getMoudleId()).getId());
                return columnTemplate;
            }).collect(Collectors.toList());
            columnTemplateMapper.insertBatchSomeColumn(columnTemplateList);
            List<ColumnRefComPlate> columnRefComPlateList = refComponentList.stream().map(refComponent -> {
                ColumnRefComPlate columnRefComPlate = new ColumnRefComPlate();
                BeanUtils.copyProperties(refComponent, columnRefComPlate);
                columnRefComPlate.setId(null);
                columnRefComPlate.setTemplateId(templateId);
                columnRefComPlate.setColumnId(cidColumnTempMap.get(refComponent.getColumnId()).getId());
                return columnRefComPlate;
            }).collect(Collectors.toList());
            comPlateMapper.insertBatchSomeColumn(columnRefComPlateList);

            transactionManager.commit(status);
        } catch (Exception e) {
            transactionManager.rollback(status);
            log.error("生成模板錯誤：", e);
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }

        return ResultVO.success(ResultCode.SUCCESS);
    }

    @Override
    public ResultVO delWeb(ModuleColumnGeneratorVo generatorVo) {
        if (generatorVo.getWebsiteId() <= 4){
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }

        Integer websiteId = generatorVo.getWebsiteId();
        if (websiteId == null) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        LambdaQueryWrapper<Moudle> moudleLqw = new LambdaQueryWrapper<Moudle>().select(Moudle::getId).eq(Moudle::getWebsiteId, websiteId);
        // 1.查询模块id集合
        List<Integer> moduleIdList = moudleMapper.selectList(moudleLqw).stream().map(Moudle::getId).collect(Collectors.toList());
        if (moduleIdList.isEmpty()) {
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        // 2.查询栏目id集合
        LambdaQueryWrapper<Column> columnLqw = new LambdaQueryWrapper<>();
        columnLqw.select(Column::getId).in(Column::getMoudleId, moduleIdList);
        List<Integer> columnIdList = columnMapper.selectList(columnLqw).stream().map(Column::getId).collect(Collectors.toList());
        LambdaQueryWrapper<ColumnRefComponent> refComponentLqw = new LambdaQueryWrapper<ColumnRefComponent>().in(ColumnRefComponent::getColumnId, columnIdList);
        // 2.真删除
        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        try {
            columnMapper.realDeleteByMoudleIds(moduleIdList);
            moudleMapper.realDeleteByIds(moduleIdList);
            refComponentMapper.delete(refComponentLqw);
            transactionManager.commit(status);
        } catch (Exception e) {
            transactionManager.rollback(status);
            log.error("", e);
            return ResultVO.fail(ResultCode.SERVE_ERROR);
        }
        return ResultVO.success(ResultCode.SUCCESS);
    }

    @Override
    public ResultVO previousNext(Integer id) {
        ColumnData columnData = columnDataMapper.selectById(id);
        List<ColumnData> columnDataList = columnDataMapper.selectList(new LambdaQueryWrapper<ColumnData>().eq(ColumnData::getJumpOrNot,0)
                .eq(ColumnData::getColumnId, columnData.getColumnId()).eq(ColumnData::getStatus, NumberConstant.NUMBER_1).orderByDesc(ColumnData::getPublishTime));
        int i = columnDataList.indexOf(columnData);
        JSONObject jsonObject = new JSONObject();
        JSONObject previousJsonObject = new JSONObject();
        JSONObject nextJsonObject = new JSONObject();
        if (columnDataList.size() == 1) {
            jsonObject.put("previous", null);
            jsonObject.put("next", null);
            return ResultVO.data(jsonObject);
        }
        if (i == 0) {
            jsonObject.put("previous", null);
            ColumnData columnData1 = columnDataList.get(1);
            nextJsonObject.put("id", columnData1.getId());
            nextJsonObject.put("title", columnData1.getTitle());
            jsonObject.put("next", nextJsonObject);
            return ResultVO.data(jsonObject);
        }
        if (i == columnDataList.size() - 1) {
            ColumnData columnData1 = columnDataList.get(columnDataList.size() - 2);
            previousJsonObject.put("id", columnData1.getId());
            previousJsonObject.put("title", columnData1.getTitle());
            jsonObject.put("previous", previousJsonObject);
            jsonObject.put("next", null);
            return ResultVO.data(jsonObject);
        }
        ColumnData previous = columnDataList.get(i - 1);
        ColumnData next = columnDataList.get(i + 1);

        previousJsonObject.put("id", previous.getId());
        previousJsonObject.put("title", previous.getTitle());

        nextJsonObject.put("id", next.getId());
        nextJsonObject.put("title", next.getTitle());

        jsonObject.put("previous", previousJsonObject);
        jsonObject.put("next", nextJsonObject);
        return ResultVO.data(jsonObject);
    }
}
